#include "GLBModel.h"

#define TINYGLTF_IMPLEMENTATION
#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "tiny_gltf.h"

#include <QDebug>
#include <vector>

GLTFModel::GLTFModel(QObject *parent) : QObject(parent) {
    m_vao = nullptr;
    m_vbo_positions = 0;
    m_vbo_normals = 0;
    m_vbo_colors = 0;
    m_ebo = 0;
    m_indexCount = 0;
}

GLTFModel::~GLTFModel() {
    cleanup();
}

void GLTFModel::initialize() {
    initializeOpenGLFunctions();
}

void GLTFModel::cleanup() {
    if (QOpenGLContext::currentContext()) {
        glDeleteBuffers(1, &m_vbo_positions);
        glDeleteBuffers(1, &m_vbo_normals);
        glDeleteBuffers(1, &m_vbo_colors);
        glDeleteBuffers(1, &m_ebo);
        if (m_vao) {
            m_vao->destroy();
            delete m_vao;
            m_vao = nullptr;
        }
    }
    m_vbo_positions = m_vbo_normals = m_vbo_colors = m_ebo = 0;
    m_indexCount = 0;
}

bool GLTFModel::loadFromFile(const std::string& filepath) {
    cleanup();
    tinygltf::Model model;
    tinygltf::TinyGLTF loader;
    std::string err, warn;

    qInfo() << "正在加载模型:" << QString::fromStdString(filepath);
    bool res = loader.LoadBinaryFromFile(&model, &err, &warn, filepath);

    if (!warn.empty()) qWarning() << "glTF 警告:" << QString::fromStdString(warn);
    if (!err.empty()) qCritical() << "glTF 错误:" << QString::fromStdString(err);
    if (!res) {
        qCritical() << "无法加载 glTF 文件!";
        return false;
    }

    std::vector<float> all_positions;
    std::vector<float> all_normals;
    std::vector<float> all_colors;
    std::vector<unsigned int> all_indices;

    for (const auto& mesh : model.meshes) {
        for (const auto& primitive : mesh.primitives) {
            unsigned int vertex_offset = all_positions.size() / 3;
            size_t vertex_count = 0;

            // --- 加载顶点位置 (Position) ---
            if (primitive.attributes.count("POSITION")) {
                const auto& accessor = model.accessors[primitive.attributes.at("POSITION")];
                vertex_count = accessor.count; // 获取顶点数，为后面可能的颜色填充做准备
                const auto& bufferView = model.bufferViews[accessor.bufferView];
                const auto& buffer = model.buffers[bufferView.buffer];
                const float* data = reinterpret_cast<const float*>(&buffer.data[bufferView.byteOffset + accessor.byteOffset]);
                all_positions.insert(all_positions.end(), data, data + accessor.count * 3);
            }

            // --- 加载顶点法线 (Normal) ---
            if (primitive.attributes.count("NORMAL")) {
                const auto& accessor = model.accessors[primitive.attributes.at("NORMAL")];
                const auto& bufferView = model.bufferViews[accessor.bufferView];
                const auto& buffer = model.buffers[bufferView.buffer];
                const float* data = reinterpret_cast<const float*>(&buffer.data[bufferView.byteOffset + accessor.byteOffset]);
                all_normals.insert(all_normals.end(), data, data + accessor.count * 3);
            }

            // --- 加载顶点颜色 (Vertex Color) ---
            if (primitive.attributes.count("COLOR_0")) {
                const auto& accessor = model.accessors[primitive.attributes.at("COLOR_0")];
                const auto& bufferView = model.bufferViews[accessor.bufferView];
                const auto& buffer = model.buffers[bufferView.buffer];
                const void* data_ptr = &buffer.data[bufferView.byteOffset + accessor.byteOffset];

                if (accessor.type == TINYGLTF_TYPE_VEC3) {
                    const float* data = static_cast<const float*>(data_ptr);
                    all_colors.insert(all_colors.end(), data, data + accessor.count * 3);
                } else if (accessor.type == TINYGLTF_TYPE_VEC4) { // 如果是4分量颜色(RGBA)
                    const float* data = static_cast<const float*>(data_ptr);
                    for (size_t i = 0; i < accessor.count; ++i) {
                        all_colors.push_back(data[i*4 + 0]); // R
                        all_colors.push_back(data[i*4 + 1]); // G
                        all_colors.push_back(data[i*4 + 2]); // B, 忽略 Alpha
                    }
                }
            } else if (vertex_count > 0) {
                // 如果模型本身不带颜色, 我们就用白色(1,1,1)填充, 保证数据对齐
                for(size_t i = 0; i < vertex_count; ++i) {
                    all_colors.push_back(1.0f);
                    all_colors.push_back(1.0f);
                    all_colors.push_back(1.0f);
                }
            }

            // --- 加载索引 (Indices) ---
            if (primitive.indices > -1) {
                const auto& accessor = model.accessors[primitive.indices];
                const auto& bufferView = model.bufferViews[accessor.bufferView];
                const auto& buffer = model.buffers[bufferView.buffer];
                const void* data_ptr = &buffer.data[bufferView.byteOffset + accessor.byteOffset];

                switch (accessor.componentType) {
                case TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT: {
                    const unsigned short* indices = static_cast<const unsigned short*>(data_ptr);
                    for (size_t i = 0; i < accessor.count; ++i) {
                        all_indices.push_back(indices[i] + vertex_offset);
                    }
                    break;
                }
                case TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT: {
                    const unsigned int* indices = static_cast<const unsigned int*>(data_ptr);
                    for (size_t i = 0; i < accessor.count; ++i) {
                        all_indices.push_back(indices[i] + vertex_offset);
                    }
                    break;
                }
                default: break;
                }
            }
        }
    }
    m_indexCount = all_indices.size();

    // --- 上传数据到 GPU ---
    m_vao = new QOpenGLVertexArrayObject(this);
    m_vao->create();
    m_vao->bind();

    // 位置 (location = 0)
    glGenBuffers(1, &m_vbo_positions);
    glBindBuffer(GL_ARRAY_BUFFER, m_vbo_positions);
    glBufferData(GL_ARRAY_BUFFER, all_positions.size() * sizeof(float), all_positions.data(), GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), nullptr);

    // 法线 (location = 1)
    if (!all_normals.empty()) {
        glGenBuffers(1, &m_vbo_normals);
        glBindBuffer(GL_ARRAY_BUFFER, m_vbo_normals);
        glBufferData(GL_ARRAY_BUFFER, all_normals.size() * sizeof(float), all_normals.data(), GL_STATIC_DRAW);
        glEnableVertexAttribArray(1);
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), nullptr);
    }

    // 颜色 (location = 2)
    if (!all_colors.empty()) {
        glGenBuffers(1, &m_vbo_colors);
        glBindBuffer(GL_ARRAY_BUFFER, m_vbo_colors);
        glBufferData(GL_ARRAY_BUFFER, all_colors.size() * sizeof(float), all_colors.data(), GL_STATIC_DRAW);
        glEnableVertexAttribArray(2);
        glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), nullptr);
    }

    // 索引 (EBO)
    glGenBuffers(1, &m_ebo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ebo);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, all_indices.size() * sizeof(unsigned int), all_indices.data(), GL_STATIC_DRAW);

    m_vao->release();
    qInfo() << "模型加载并上传到GPU成功! (带颜色) 总顶点数:" << all_positions.size() / 3 << ", 总索引数:" << m_indexCount;
    return true;
}

void GLTFModel::draw() {
    if (!m_vao || m_indexCount == 0) return;
    QOpenGLVertexArrayObject::Binder vaoBinder(m_vao);
    glDrawElements(GL_TRIANGLES, m_indexCount, GL_UNSIGNED_INT, nullptr);
}
